use std::sync::Arc;

use axum::{
    extract::{DefaultBodyLimit, Multipart},
    response::IntoResponse,
    routing::post,
    Extension, Json, Router,
};
use tower_http::limit::RequestBodyLimitLayer;

use crate::{
    config,
    server::{AppState, SenceVoiceResponse, TextResponse},
    Result,
};

pub fn router() -> Router {
    Router::new()
        .route("/", post(upload_audio))
        .layer(DefaultBodyLimit::disable())
        .layer(RequestBodyLimitLayer::new(config::UPLOAD_FILE_SIZE_LIMIT))
}

async fn upload_audio(
    Extension(app_state): Extension<Arc<AppState>>,
    mut files: Multipart,
) -> Result<impl IntoResponse> {
    while let Some(file) = files.next_field().await.unwrap_or_default() {
        if let Some(field_name) = file.name() {
            let suffix = file
                .file_name()
                .unwrap_or("")
                .split('.')
                .last()
                .unwrap_or("")
                .to_owned();
            println!("field_name: {field_name}, suffix: {suffix}");

            if field_name == "file" {
                if let Ok(audio) = file.bytes().await {
                    // 时间
                    let now = chrono::Local::now();
                    // 文件名
                    let file_name = format!("{}.{suffix}", now.format("%Y%m%d%H%M%S%9f"));
                    let path = format!("uploads/{}", now.format("%Y%m%d"));
                    // 创建目录
                    if tokio::fs::create_dir_all(&path).await.is_ok() {
                        // 文件全路径
                        let file_path = format!("{}/{}", path, file_name);
                        // 写入文件
                        if tokio::fs::write(&file_path, &audio).await.is_ok() {
                            let part = reqwest::multipart::Part::bytes(audio.to_vec())
                                .file_name(file_name);
                            let form = reqwest::multipart::Form::new()
                                .part("files", part)
                                .text("keys", now.format("%Y%m%d%H%M%S%9f").to_string());

                            let resp = reqwest::Client::new()
                                .post(format!("{}/api/v1/asr", config::AUDIO_HOST))
                                .multipart(form)
                                .send()
                                .await;

                            if let Ok(resp) = resp {
                                if let Ok(text_response) = resp.json::<SenceVoiceResponse>().await {
                                    let word = text_response.result[0].clean_text.clone();
                                    if word.contains("点头") || word.contains("招呼") {
                                        crate::utils::head_point(app_state.clone()).await;
                                    } else if word.contains("百岁山") || word.contains("左边")
                                    {
                                        crate::utils::to_save_go_home(
                                            app_state.clone(),
                                            [12142, 66449, -1866, -93769, 3591, 73210, 8751],
                                        )
                                        .await;
                                    } else if word.contains("怡宝") || word.contains("右边") {
                                        crate::utils::to_save_go_home(
                                            app_state.clone(),
                                            [-9299, 64712, 977, -100618, -1338, 78106, -6777],
                                        )
                                        .await;
                                    }

                                    return Ok(Json(TextResponse {
                                        text: text_response.result[0].clean_text.clone(),
                                    }));
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    Err(crate::Error::Voice)
}
